﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Isotop.Text.Tests
{
	class LazyStringBuilderPerformanceTests
	{
		public static void Main(string[] args)
		{
			foreach (var length in new[] { 1, 30, 100, 200, 300 })
				TestBoth(length, 3);
			Console.ReadKey();
		}

		static string GetCommaList(IEnumerable<string> list)
		{
			var arr = list.ToArray();
			StringBuilder sb = new StringBuilder();
			sb.Append("{");
			for (int i = 0; i < arr.Length; i++)
			{
				if (i != 0)
				{
					bool last = (i == arr.Length - 1);
					if (last)
						sb.Append(" and ");
					else
						sb.Append(", ");
				}
				sb.Append(arr[i]);
			}
			sb.Append("}");
			return sb.ToString();
		}

		static void TestBoth(int stringLength, int repetions)
		{
			var ss = GetSomeStrings(stringLength);
			Console.WriteLine("NormalStringBuilder");
			var res = Time(ss, TestNormalStringBuilder, repetions);
			Console.WriteLine(res.Sum() + "," + res.Average() + "," + res.Median());
			Console.WriteLine("LazyStringBuilder");
			res = Time(ss, TestLazyStringBuilder, repetions);
			Console.WriteLine(res.Sum() + "," + res.Average() + "," + res.Median());
		}


		public void TestCorrect()
		{
			var res = GetCommaListLazy(new[] { "Ett", "Två", "Tre" });
			Console.WriteLine("Here: ");
			Console.WriteLine(res);
		}

		public void TestCorrect2()
		{
			var res = GetCommaListLazy(new[] { "Ettxxxxxxxxxxxxxxx##", "Tvåxxxxxxxxxxxxxxx##", "Trexxxxxxxxxxxxxxxxxx##" });
			Console.WriteLine("Here: ");
			Console.WriteLine(res);
		}

		public void TestCorrect1()
		{
			var s = GetSomeStrings(1);
			var res = GetCommaListLazy(s);
			Console.WriteLine(res);
		}

		public void TestCorrect3()
		{
			var s = GetSomeStrings(100);
			var res = GetCommaListLazy(s);
			//Console.WriteLine(res);
		}

		public void TestCorrect30()
		{
			var s = GetSomeStrings(30);
			var res = GetCommaListLazy(s);
			//Console.WriteLine(res);
		}

		/// <summary>
		/// For comparison
		/// </summary>
		//static string GetCommaList(IEnumerable<string> list)
		//{
		//   var arr = list.ToArray();
		//   var sb = new StringBuilder();
		//   sb.Append("{");
		//   for (int i = 0; i < arr.Length; i++)
		//   {
		//      if (i != 0)
		//      {
		//         bool last = (i == arr.Length - 1);
		//         if (last)
		//            sb.Append(" and ");
		//         else
		//            sb.Append(", ");
		//      }
		//      sb.Append(arr[i]);
		//   }
		//   sb.Append("}");
		//   return sb.ToString();
		//}

		static string GetCommaListLazy(IEnumerable<string> list)
		{
			var arr = list.ToArray();
			var sb = new LazyStringBuilder();
			sb.Append("{");
			for (int i = 0; i < arr.Length; i++)
			{
				if (i != 0)
				{
					bool last = (i == arr.Length - 1);
					if (last)
						sb.Append(" and ");
					else
						sb.Append(", ");
				}
				sb.Append(arr[i]);
			}
			sb.Append("}");
			//Console.WriteLine("Array length: " + sb._strings.Index);
			return sb.ToString();
		}

		public static void TestLazyStringBuilder(string[] someStrings)
		{
			for (int i = 0; i < 1000; i++)
				GetCommaListLazy(someStrings);
		}

		public static void TestNormalStringBuilder(string[] someStrings)
		{
			for (int i = 0; i < 1000; i++)
				GetCommaList(someStrings);
		}

		static IEnumerable<long> Time<T>(T indata, Action<T> toTime, int times)
		{
			long[] res = new long[times];

			for (int i = 0; i < times; i++)
			{
				var sw = Stopwatch.StartNew();

				toTime(indata);

				sw.Stop();
				res[i] = sw.ElapsedMilliseconds;
			}

			return res;
		}

		static string[] GetSomeStrings(int length)
		{
			string[] res = new string[1000];
			string temp = "";
			for (int i = 0; i < length; i++)
				temp += "X";
			for (int i = 0; i < 1000; i++)
				res[i] = temp;
			return res;
		}
	}

	internal class LazyStringBuilder2
	{
		StringBuilder _sb = new StringBuilder();

		//public void Init()
		//{
		//   _sb = new StringBuilder();
		//}

		public void Append(string and)
		{
			_sb.Append(and);
		}

		public override string ToString()
		{
			return _sb.ToString();
		}
	}


}